//
//  OpenglCCView.swift
//  MacTest
//
//  Created by yuanxc on 2024/5/25.
//

import Foundation
import Cocoa
import OpenGL.GL3

class OpenglCCView: NSOpenGLView {

    //MARK: - Properties
    fileprivate var lifeDuration: CGFloat = 0
    fileprivate var program: GLuint = 0
    fileprivate var vertexArray: GLuint = 0

    //MARK: - Life Cycle
    required init?(coder decoder: NSCoder) {
        super.init(coder: decoder)

        let openGLContextConfigured = setupOpenGLContext()
        if !openGLContextConfigured {
            print("Prepare OpenGLContextFailed...")
        }
    }

    override init?(frame frameRect: NSRect, pixelFormat format: NSOpenGLPixelFormat?) {
        super.init(frame: frameRect, pixelFormat: format)
        let openGLContextConfigured = setupOpenGLContext()
        if !openGLContextConfigured {
            print("Prepare OpenGLContextFailed...")
        }
    }

    deinit {
        glDeleteProgram(program)
        glDeleteVertexArrays(1, &vertexArray)
    }

    //MARK: - Override
    override func prepareOpenGL() {
        super.prepareOpenGL()

        if let versionString = glGetString(GLenum(GL_VERSION)) {
            print("GL_VERSION: " + String(cString: versionString))
        }
        if let renderString = glGetString(GLenum(GL_RENDERER)) {
            print("GL_RENDERER: " + String(cString: renderString))
        }
        if let vendorString = glGetString(GLenum(GL_VENDOR)) {
            print("GL_VENDOR: " + String(cString: vendorString))
        }
        if let glVersionString = glGetString(GLenum(GL_SHADING_LANGUAGE_VERSION)) {
            print("GL_SHADING_LANGUAGE_VERSION: " + String(cString: glVersionString))
        }

        setupOpenGLShaders(&program, &vertexArray)
    }

    override func reshape() {
        super.reshape()
        let bounds = self.bounds
        glViewport(0, 0, GLsizei(NSWidth(bounds)), GLsizei(NSHeight(bounds)))
    }


    override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
        render(program)
    }

    //MARK: - Private Methods
    fileprivate func setupOpenGLContext() -> Bool {
        var pixelFormatAttributes: [NSOpenGLPixelFormatAttribute] =
            [UInt32(NSOpenGLPFAColorSize), 32,
             UInt32(NSOpenGLPFAAccelerated),
             UInt32(NSOpenGLPFAOpenGLProfile), UInt32(NSOpenGLProfileVersion4_1Core), 0]
        guard let pixelFormat = NSOpenGLPixelFormat(attributes: &pixelFormatAttributes) else {
            return false
        }

        let currentOpenGLContext = NSOpenGLContext(format: pixelFormat, share: nil)
        self.openGLContext = currentOpenGLContext
        self.openGLContext?.makeCurrentContext()
        return true
    }
}
